{ SUBROUTINES FOR ADVENTURE }
PROCEDURE NAMEANDPW;
VAR
  ACHR : CHAR;
  ACHAR : STRING[1];
BEGIN { NAMENADPW }
  WRITELN('ENTER YOUR NAME PLEASE.');
  READLN(NAMEOFUSER);
  WRITELN('ENTER YOUR PASSWORD ');
  READ(KEYBOARD,ACHR);
  ACHAR:=' ';
  TESTPW:='';
  WHILE NOT EOLN(KEYBOARD) DO
  BEGIN
    ACHAR[1]:=ACHR;
    IF 8=ORD(ACHR) THEN
      IF LENGTH(TESTPW)>0 THEN
      BEGIN
        DELETE(TESTPW,LENGTH(TESTPW),1);
        WRITE(CHR(8),' ',CHR(8));
      END
      ELSE
    ELSE
    BEGIN
      WRITE('X');
      TESTPW:=CONCAT(TESTPW,ACHAR);
    END;
    READ(KEYBOARD,ACHR);
  END;
  NAMEOFUSER:=CONCAT(NAMEOFUSER,'.AVSV');
END;  { NAMEANDPW }
FUNCTION GETSCORE(SCORECMD:BOOLEAN) : INTEGER;
VAR
  I,K,SCORE : INTEGER;
BEGIN {GETSCORE}
  MAXSCORE:=0;
  SCORE:=0;
  FOR I:=50 TO MAXTRS DO
    IF ARY^.PTEXT[I]<>0 THEN
    BEGIN
      IF I=CHEST THEN
        K:=14
      ELSE
        IF I>CHEST THEN
          K:=16
        ELSE
          K:=12;
      IF (VARY^.PROP[I]>=0) THEN
        SCORE:=SCORE+2;
      IF (VARY^.PLACE[I]=3) AND (VARY^.PROP[I]=0) THEN
        SCORE:=SCORE+K-2;
      MAXSCORE:=MAXSCORE+K;
    END;
  SCORE:=SCORE+(MAXDIE-VBL^.NUMDIE)*10;
  MAXSCORE:=MAXSCORE+MAXDIE*10;
  IF VBL^.DFLAG<>0 THEN
    SCORE:=SCORE+25;
  MAXSCORE:=MAXSCORE+25;
  IF NOT (GAVEUP OR SCORECMD) THEN
    SCORE:=SCORE+4;
  MAXSCORE:=MAXSCORE+4;
  IF VBL^.CLOSING THEN
    SCORE:=SCORE+25;
  MAXSCORE:=MAXSCORE+25;
  CASE BONUS OF
    0 : SCORE:=SCORE+10;
    135 : SCORE:=SCORE+25;
    134 : SCORE:=SCORE+30;
    133 : SCORE:=SCORE+45;
  END;
  MAXSCORE:=MAXSCORE+45;
  IF VARY^.PLACE[MAGAZINE]=108 THEN
    SCORE:=SCORE+1;
  MAXSCORE:=MAXSCORE+1;
  SCORE:=SCORE+2;
  MAXSCORE:=MAXSCORE+2;
  FOR I:=1 TO HNTSIZ DO
    IF VARY^.HINTED[I] THEN
      SCORE:=SCORE-ARY^.HINTS[I,2];
  GETSCORE:=SCORE;
END;  {GETSCORE}
FUNCTION TOTING(OBJECT:INTEGER):BOOLEAN;
BEGIN {TOTING}
  TOTING:=(VARY^.PLACE[OBJECT]=-1);
END;  {TOTING}
FUNCTION AT(OBJECT:INTEGER):BOOLEAN;
BEGIN {AT}
  AT:=(VARY^.PLACE[OBJECT]=VBL^.LOC) OR
      (VARY^.FIXED[OBJECT]=VBL^.LOC);
END;  {AT}
FUNCTION MIN(I,J:INTEGER):INTEGER;
BEGIN {MIN}
  IF J<I THEN
    MIN:=J
  ELSE
    MIN:=I;
END;  {MIN}
FUNCTION MAX(I,J:INTEGER):INTEGER;
BEGIN {MAX}
  IF J>I THEN
    MAX:=J
  ELSE
    MAX:=I;
END;  {MAX}
FUNCTION RAN(NUM:INTEGER):INTEGER;
VAR
  TEMP : INTEGER;
  TEMP2 : REAL;
BEGIN {RAN}
  TEMP:=SEED*899;
  IF TEMP<0 THEN
    TEMP:=TEMP+32767+1;
  TEMP2:=(TEMP-1)/32767.0;
  RAN:=TRUNC(TEMP2*NUM);
  SEED:=TEMP;
END;  {RAN}
FUNCTION PERCENT(I:INTEGER):BOOLEAN;
BEGIN {PERCENT}
  PERCENT:=(RAN(100)<I);
END;  {PERCENT}
FUNCTION HERE(OBJECT:INTEGER):BOOLEAN;
BEGIN {HERE}
  HERE:=(VARY^.PLACE[OBJECT]=VBL^.LOC) OR TOTING(OBJECT);
END;  {HERE}
FUNCTION DARK : BOOLEAN;
BEGIN {DARK}
  DARK:=((VARY^.COND[VBL^.LOC] MOD 2)=0) AND 
        ((VARY^.PROP[LAMP]=0) OR NOT HERE(LAMP));
END;  {DARK}
FUNCTION FORCED(LOC:INTEGER):BOOLEAN;
BEGIN {FORCED}
  FORCED:=VARY^.COND[LOC]=2;
END;  {FORCED}
FUNCTION BITSET(I,J:INTEGER):BOOLEAN;
VAR
  K,TEMP : INTEGER;
BEGIN {BITSET}
  TEMP:=VARY^.COND[I];
  FOR K:=1 TO J DO
    TEMP:=TEMP DIV 2;
  BITSET:=(TEMP MOD 2) = 1;
END;  {BITSET}
FUNCTION LIQ2(PBOTL:INTEGER): INTEGER;
VAR
  TEMP : INTEGER;
BEGIN {LIQ2}
  TEMP:=PBOTL DIV 2;
  LIQ2:=((1-PBOTL)*WATER+TEMP*(WATER+OIL));
END;  {LIQ2}
FUNCTION LIQ:INTEGER;
BEGIN {LIQ}
  LIQ:=LIQ2(MAX(VARY^.PROP[BOTTLE],-1-VARY^.PROP[BOTTLE]));
END;  {LIQ}
FUNCTION LIQLOC(LOC:INTEGER):INTEGER;
VAR
  TEMP1,TEMP2 : INTEGER;
BEGIN {LIQLOC}
  TEMP1:=(VARY^.COND[LOC] DIV 2) * 2; {EVEN COND ONLY}
  TEMP2:=VARY^.COND[LOC] DIV 4;
  LIQLOC:=LIQ2((TEMP1 MOD 8 - 5) * (TEMP2 MOD 2) + 1);
END;  {LIQLOC}
FUNCTION VOCAB(WORD:STRING;WHAT:INTEGER):INTEGER;
VAR
  I,J,K : INTEGER;
BEGIN {VOCAB}
  I:=1;
  J:=300;
  REPEAT
    K:=(I+J) DIV 2;
    IF ARY^.ATAB[K]<=WORD THEN
      I:=K+1;
    IF ARY^.ATAB[K]>=WORD THEN
      J:=K-1;
  UNTIL I>J;
  IF K>1 THEN
    IF ARY^.ATAB[K-1]=WORD THEN
      K:=K-1; {FIND FIRST WORD}
  VOCAB:=-1;
  IF ARY^.ATAB[K]=WORD THEN
    VOCAB:=ARY^.KTAB[K];
  IF WHAT>=0 THEN
  BEGIN
    WHILE (ARY^.ATAB[K]=WORD) AND
          (WHAT<>(ARY^.KTAB[K] DIV 1000)) DO
      K:=K+1;
    IF ARY^.ATAB[K]=WORD THEN
      VOCAB:=ARY^.KTAB[K] MOD 1000;
  END;
END;  {VOCAB}
PROCEDURE CARRY(OBJECT,WHERE:INTEGER);
VAR
  TEMP : INTEGER;
PROCEDURE LINKUP;
BEGIN {LINKUP}
  TEMP:=VARY^.ATLOC[WHERE];
  WHILE (VARY^.LINK[TEMP]<>OBJECT) DO
    TEMP:=VARY^.LINK[TEMP];
  VARY^.LINK[TEMP]:=VARY^.LINK[OBJECT];
END;  {LINKUP}
BEGIN {CARRY}
  IF OBJECT<=100 THEN
    IF VARY^.PLACE[OBJECT]<>-1 THEN
    BEGIN
      VARY^.PLACE[OBJECT]:=-1;
      VBL^.HLDING:=VBL^.HLDING+1;
      IF VARY^.ATLOC[WHERE]=OBJECT THEN
        VARY^.ATLOC[WHERE]:=VARY^.LINK[OBJECT]
      ELSE
        LINKUP
    END
    ELSE
  ELSE
    IF VARY^.ATLOC[WHERE]=OBJECT THEN
      VARY^.ATLOC[WHERE]:=VARY^.LINK[OBJECT]
    ELSE
      LINKUP
END;  {CARRY}
PROCEDURE DROP(OBJECT,WHERE:INTEGER);
BEGIN {DROP}
  IF OBJECT>100 THEN
    VARY^.FIXED[OBJECT-100]:=WHERE
  ELSE
  BEGIN
    IF VARY^.PLACE[OBJECT]=-1 THEN
      VBL^.HLDING:=VBL^.HLDING-1;
    VARY^.PLACE[OBJECT]:=WHERE;
  END;
  IF WHERE>0 THEN
  BEGIN
    VARY^.LINK[OBJECT]:=VARY^.ATLOC[WHERE];
    VARY^.ATLOC[WHERE]:=OBJECT;
  END;
END;  {DROP}
PROCEDURE MOVE(OBJECT,WHERE:INTEGER);
VAR
  FROM : INTEGER;
BEGIN {MOVE}
  IF OBJECT>100 THEN
    FROM:=VARY^.FIXED[OBJECT-100]
  ELSE
    FROM:=VARY^.PLACE[OBJECT];
  IF (FROM>0) AND (FROM <= 300) THEN
    CARRY(OBJECT,FROM);
  DROP(OBJECT,WHERE);
END;  {MOVE}
PROCEDURE JUGGLE(OBJECT:INTEGER);
BEGIN {JUGGLE}
  MOVE(OBJECT,VARY^.PLACE[OBJECT]);
  MOVE(OBJECT+100,VARY^.FIXED[OBJECT]);
END;  {JUGGLE}
PROCEDURE DESTROY(OBJECT:INTEGER);
BEGIN {DESTROY}
  MOVE(OBJECT,0);
END;  {DESTROY}
FUNCTION PUT(OBJECT,WHERE,PVAL : INTEGER):INTEGER;
BEGIN {PUT}
  MOVE(OBJECT,WHERE);
  PUT:=(-1)-PVAL;
END;  {PUT}
PROCEDURE SPEAK(MSG:INTEGER);
VAR
  I : INTEGER;
  MTEMP : STRING[6];
  MTEMP2 : STRING;
  MTEXT : STRING[255];
PROCEDURE HOLDUP;
BEGIN { HOLDUP }
  LINE:=LINE+1;
  IF LINE>=(TERMHIGHT-1) THEN
  BEGIN
    LINE:=1;
    WRITE(CHR(7),'         PRESS <RETURN> TO CONTINUE');
    READLN;
  END;
END;  { HOLDUP }
BEGIN {SPEAK}
  MTEMP:='      ';
  MTEXT:='';
  IF MSG>0 THEN
  BEGIN
    SEEK(MSGFILE,MSG);
    REPEAT
      GET(MSGFILE);
      FOR I:=1 TO 6 DO
        MTEMP[I]:=MSGFILE^[I];
      IF ORD(MTEMP[1])>128 THEN
        MTEMP[1]:=CHR(ORD(MTEMP[1])-128);
      IF ORD(MTEMP[2])>128 THEN
        MTEMP[2]:=CHR(ORD(MTEMP[2])-128);
      MTEXT:=CONCAT(MTEXT,MTEMP);
      IF LENGTH(MTEXT)>TERMWIDTH THEN
      BEGIN
        I:=TERMWIDTH;
        WHILE MTEXT[I]<>' ' DO
          I:=I-1;
        MTEMP2:=COPY(MTEXT,1,I-1);
        DELETE(MTEXT,1,I);
        WRITELN(MTEMP2);
        HOLDUP;
      END;
    UNTIL ORD(MSGFILE^[1])>128;
    IF MTEXT<>'      ' THEN {DONT PRINT DUMMY MSG}
    BEGIN
      WRITELN(MTEXT);
      HOLDUP;
    END;
  END;
END;  {SPEAK}
PROCEDURE PSPEAK(MSG,SKIP:INTEGER);
VAR
  I,M : INTEGER;
BEGIN {PSPEAK}
  M:=ARY^.PTEXT[MSG];
  SEEK(MSGFILE,M);
  FOR I:=0 TO SKIP DO
  BEGIN
    REPEAT
      GET(MSGFILE);
      M:=M+1;
    UNTIL ORD(MSGFILE^[1])>128;
  END;
  GET(MSGFILE); { INSURE GET BETWEEN SEEKS}
  SPEAK(M);
END;  {PSPEAK}
FUNCTION YES(MSG,SPKYES,SPKNO:INTEGER):BOOLEAN;
VAR
  INLINE : STRING;
BEGIN {YES}
  YEA:=FALSE;
  SKIPIT:=FALSE;
  IF MSG<>0 THEN
    SPEAK(ARY^.RTEXT[MSG]);
  LINE:=1;
  REPEAT
    IF SKIPIT THEN
      WRITELN('PLEASE ANSWER THE QUESTION WITH YES OR NO');
    SKIPIT:=TRUE;
    READLN(INLINE);
  UNTIL (INLINE='YES') OR (INLINE='Y') OR
        (INLINE='NO')  OR (INLINE='N') OR
        (INLINE='yes') OR (INLINE='y') OR
        (INLINE='no')  OR (INLINE='n');
  YEA:=(INLINE='YES') OR (INLINE='Y') OR
       (INLINE='yes') OR (INLINE='y');
  IF (INLINE='yes') OR (INLINE='y') OR
     (INLINE='no')  OR (INLINE='n')THEN
    WRITELN(CHR(7),'YOU WONT GET VERY FAR IN LOWER CASE !');
  IF YEA THEN
    SPKNO:=SPKYES;
  IF SPKNO<>0 THEN
    SPEAK(ARY^.RTEXT[SPKNO]);
  YES:=YEA;
END;  {YES}
PROCEDURE ERRORHALT(I:INTEGER);
BEGIN {ERRORHALT}
  WRITELN;
  WRITELN('FATAL ERROR # ',I,' ---- BYE!');
  HALT;
END;  {ERRORHALT}
PROCEDURE SET_NEW_LOC; FORWARD;
PROCEDURE TESTCLOSE;
VAR
  I : INTEGER;
BEGIN { TESTCLOSE }
  IF (NEWLOC IN [1..8]) AND VBL^.CLOSING THEN
    BEGIN
      SPEAK(ARY^.RTEXT[130]);
      NEWLOC:=VBL^.LOC;
      IF NOT VBL^.PANIC THEN VBL^.CLOCK2:=15;
      VBL^.PANIC:=TRUE;
    END;
  IF (NEWLOC<>VBL^.LOC) AND NOT FORCED(VBL^.LOC)
      AND NOT BITSET(VBL^.LOC,3) THEN
    FOR I:=1 TO 5 DO
      IF (VARY^.ODLOC[I]=NEWLOC) AND VARY^.DSEEN[I] THEN
      BEGIN
        NEWLOC:=VBL^.LOC;
        SPEAK(ARY^.RTEXT[2]);
        I:=5;
      END;
END;  { TESTCLOSE }
PROCEDURE DWARFSTUFF;
VAR
  LASTLOC : INTEGER;
  TBITSET,TFORCED : BOOLEAN;
PROCEDURE PIRATESTUFF;
BEGIN { PIRATESTUFF}
  K:=0;
  STEAL:=FALSE;
  FOR J:=50 TO MAXTRS DO
  BEGIN
    IF (J=PYRAMID) AND ((VBL^.LOC=ARY^.PLAC[PYRAMID]) OR
       (VBL^.LOC=ARY^.PLAC[EMERALD])) THEN { NOTHING }
    ELSE
    BEGIN
      STEAL:=STEAL OR TOTING(J);
      IF VARY^.PLACE[J]=VBL^.LOC THEN
        K:=1;
    END;
  END;
  IF STEAL THEN
  BEGIN
    SPEAK(ARY^.RTEXT[128]);
    IF VARY^.PLACE[MESSAGE]=0 THEN
      MOVE(CHEST,VBL^.CHLOC);
    MOVE(MESSAGE,VBL^.CHLOC2);
    FOR J:=50 TO MAXTRS DO
    BEGIN
      IF (J=PYRAMID) AND ((VBL^.LOC=ARY^.PLAC[PYRAMID]) OR
       (VBL^.LOC=ARY^.PLAC[EMERALD])) THEN { NOTHING }
      ELSE
      BEGIN
        IF (VARY^.PLACE[J]=VBL^.LOC) AND (VARY^.FIXED[J]=0) THEN
          CARRY(J,VBL^.LOC);
        IF TOTING(J) THEN
          DROP(J,VBL^.CHLOC);
      END;
    END;
    VARY^.DLOC[6]:=VBL^.CHLOC;
    VARY^.ODLOC[6]:=VBL^.CHLOC;
    VARY^.DSEEN[6]:=FALSE;
  END
  ELSE
  BEGIN
    IF (VBL^.TALLY=(VBL^.TALLY2+1)) AND
       (K=0) AND (VARY^.PLACE[CHEST]=0) AND
       HERE(LAMP) AND (VARY^.PROP[LAMP]=1) THEN
    BEGIN
      SPEAK(ARY^.RTEXT[186]);
      MOVE(CHEST,VBL^.CHLOC);
      MOVE(MESSAGE,VBL^.CHLOC2);
      VARY^.DLOC[6]:=VBL^.CHLOC;
      VARY^.ODLOC[6]:=VBL^.CHLOC;
      VARY^.DSEEN[6]:=FALSE;
    END
    ELSE
      IF (VARY^.ODLOC[6]<>VARY^.DLOC[6]) AND PERCENT(20) THEN
        SPEAK(ARY^.RTEXT[127]);
  END;
END;  { PIRATESTUFF}
BEGIN { DWARFSTUFF }
  IF VBL^.DFLAG=1 THEN
    IF (VBL^.LOC>=15) AND PERCENT(95) THEN
    BEGIN
      VBL^.DFLAG:=2;
      FOR I:=1 TO 2 DO
        IF PERCENT(50) THEN
          VARY^.DLOC[1+RAN(5)]:=0;
      FOR I:=1 TO 5 DO
      BEGIN
        IF VARY^.DLOC[I]=VBL^.LOC THEN
          VARY^.DLOC[I]:=DALTLC;
        VARY^.ODLOC[I]:=VARY^.DLOC[I];
      END;
      SPEAK(ARY^.RTEXT[3]);
      DROP(AXE,VBL^.LOC);
    END
    ELSE
  ELSE
  BEGIN
    VBL^.DTOTAL:=0;
    ATTACK:=0;
    STICK:=0;
    FOR I:=1 TO 6 DO
      IF VARY^.DLOC[I]<>0 THEN
      BEGIN
        J:=1;
        KK:=ARY^.KEY[VARY^.DLOC[I]];
        IF KK<>0 THEN
        REPEAT
          NEWLOC:=ARY^.TRAVEL2[KK];
          IF (J>1) AND (J<=21) THEN
            LASTLOC:=VARY^.TK[J-1];
          IF NEWLOC<=150 THEN
          BEGIN
            TBITSET:=BITSET(NEWLOC,3);
            TFORCED:=FORCED(NEWLOC);
          END
          ELSE
          BEGIN
            TBITSET:=FALSE;
            TFORCED:=FALSE;
          END;
          IF (NEWLOC>300) OR (NEWLOC<15) OR
             (NEWLOC=VARY^.ODLOC[I]) OR
             ((J>1) AND (NEWLOC=LASTLOC)) OR (J>=20) OR
             (NEWLOC=VARY^.DLOC[I]) OR TFORCED OR
             ((I=6) AND TBITSET) OR
             (ARY^.TRAVEL3[KK]=100) THEN
          ELSE
          BEGIN
            VARY^.TK[J]:=NEWLOC;
            J:=J+1;
          END;
          KK:=KK+1;
        UNTIL ARY^.TRAVEL[KK-1]<0;
        VARY^.TK[J]:=VARY^.ODLOC[I];
        IF J>=2 THEN J:=J-1;
        J:=1+RAN(J);
        VARY^.ODLOC[I]:=VARY^.DLOC[I];
        VARY^.DLOC[I]:=VARY^.TK[J];
        VARY^.DSEEN[I]:=(VARY^.DSEEN[I] AND (VBL^.LOC>=15)) OR
             (VARY^.DLOC[I]=VBL^.LOC) OR
             (VARY^.ODLOC[I]=VBL^.LOC);
        IF VARY^.DSEEN[I] THEN
        BEGIN
          VARY^.DLOC[I]:=VBL^.LOC;
          IF I=6 THEN
            IF (VBL^.LOC<>VBL^.CHLOC) AND (VARY^.PROP[CHEST]<0) THEN
              PIRATESTUFF
            ELSE
          ELSE
          BEGIN
            VBL^.DTOTAL:=VBL^.DTOTAL+1;
            IF VARY^.ODLOC[I]=VARY^.DLOC[I] THEN
            BEGIN
              ATTACK:=ATTACK+1;
              IF VBL^.KNFLOC>=0 THEN VBL^.KNFLOC:=VBL^.LOC;
              IF RAN(1000)<(95*(VBL^.DFLAG-2)) THEN
                STICK:=STICK+1;
            END;
          END;
        END;
      END;
    END;
  IF VBL^.DTOTAL<>0 THEN
  BEGIN
    IF VBL^.DTOTAL=1 THEN
      SPEAK(ARY^.RTEXT[4])
    ELSE
    BEGIN
      WRITE('THERE ARE ',VBL^.DTOTAL,' THREATENING ');
      WRITELN('LITTLE DWARVES IN THE ROOM WITH YOU');
    END;
    IF ATTACK<>0 THEN
    BEGIN
      IF VBL^.DFLAG=2 THEN
        VBL^.DFLAG:=3;
      IF ATTACK=1 THEN
      BEGIN
        SPEAK(ARY^.RTEXT[5]);
        K:=52;
      END
      ELSE
      BEGIN
        K:=6;
        WRITE(ATTACK,' OF THEM THROW KNIVES AT YOU.');
      END;
      IF STICK>1 THEN
        WRITELN(STICK,' OF THEM GET YOU!')
      ELSE
        SPEAK(ARY^.RTEXT[K+STICK]);
      IF STICK<>0 THEN
      BEGIN
        VBL^.OLDLC2:=VBL^.LOC;
        HE_DIED:=TRUE;
      END;
    END;
  END;
END;  { DWARFSTUFF }
PROCEDURE DESCRIBE_CURRENT_LOCATION;
BEGIN { DESCRIBE_CURRENT_LOCATION}
  IF VBL^.LOC=0 THEN
  BEGIN
    HE_DIED:=TRUE;
    EXIT(DESCRIBE_CURRENT_LOCATION);
  END;
  KK:=ARY^.STEXT[VBL^.LOC];
  IF ((VARY^.ABB[VBL^.LOC] MOD VBL^.ABBNUM)=0) OR (KK=0) THEN
    KK:=ARY^.LTEXT[VBL^.LOC];
  IF (NOT FORCED(VBL^.LOC)) AND DARK THEN
  BEGIN
    IF VBL^.WZDARK AND PERCENT(35) THEN
    BEGIN
      HE_DIED:=TRUE;
      PIT:=TRUE;
      EXIT(DESCRIBE_CURRENT_LOCATION);
    END;
    KK:=ARY^.RTEXT[16];
  END;
  IF TOTING(BEAR) THEN
    SPEAK(ARY^.RTEXT[141]);
  SPEAK(KK);
  K:=1;
  IF FORCED(VBL^.LOC) THEN
    BEGIN
      SET_NEW_LOC;
      NEWLOCSET:=TRUE;
      EXIT(DESCRIBE_CURRENT_LOCATEION);
    END;
  IF (VBL^.LOC=33) AND PERCENT(25) AND NOT VBL^.CLOSING THEN
    SPEAK(ARY^.RTEXT[8]);
  IF NOT DARK THEN
  BEGIN
    VARY^.ABB[VBL^.LOC]:=VARY^.ABB[VBL^.LOC]+1;
    I:=VARY^.ATLOC[VBL^.LOC];
    WHILE I<>0 DO
    BEGIN
      VBL^.OBJ:=I;
      IF VBL^.OBJ>100 THEN
        VBL^.OBJ:=VBL^.OBJ-100;
      IF (VBL^.OBJ=STEPS) AND TOTING(NUGGET) THEN
      ELSE
      BEGIN
        IF VARY^.PROP[VBL^.OBJ]<0 THEN
        BEGIN
          IF NOT VBL^.CLOSED THEN
          BEGIN
            VARY^.PROP[VBL^.OBJ]:=0;
            IF (VBL^.OBJ=RUG) OR (VBL^.OBJ=CHAIN) THEN
              VARY^.PROP[VBL^.OBJ]:=1;
            VBL^.TALLY:=VBL^.TALLY-1;
            IF (VBL^.TALLY=VBL^.TALLY2) AND (VBL^.TALLY<>0) THEN
              VBL^.LIMIT:=MIN(35,VBL^.LIMIT);
          END;
        END;
        IF NOT VBL^.CLOSED THEN
        BEGIN
          KK:=VARY^.PROP[VBL^.OBJ];
          IF (VBL^.OBJ=STEPS) AND (VBL^.LOC=VARY^.FIXED[STEPS]) THEN
            KK:=1;
          PSPEAK(VBL^.OBJ,KK);
        END;
      END; 
      I:=VARY^.LINK[I];
    END; { WHILE I<>0 DO}
  END;
END; { DESCRIBE_CURRENT_LOCATION }
PROCEDURE CHECKHINTS;
PROCEDURE GIVEHINT;
BEGIN {GIVEHINT}
  VARY^.HINTLC[HINT]:=0;
  IF YES(ARY^.HINTS[HINT,3],0,54) THEN
  BEGIN
    WRITE('I AM PREPARED TO GIVE YOU A HINT, BUT ');
    WRITELN(' IT WILL COST YOU ',ARY^.HINTS[HINT,2],' POINTS');
    VARY^.HINTED[HINT]:=YES(175,ARY^.HINTS[HINT,4],54);
    IF VARY^.HINTED[HINT] AND (VBL^.LIMIT>30) THEN
      VBL^.LIMIT:=VBL^.LIMIT+30*ARY^.HINTS[HINT,2];
  END;
END;  {GIVEHINT}
PROCEDURE CAVEHINT;
BEGIN {CAVEHINT}
  IF (VARY^.PROP[GRATE]=0) AND NOT HERE(KEYS) THEN
    GIVEHINT
  ELSE
    VARY^.HINTLC[HINT]:=0;
END;  {CAVEHINT}
PROCEDURE BIRDHINT;
BEGIN {BIRDHINT}
  IF HERE(BIRD) AND TOTING(ROD) AND (VBL^.OBJ=BIRD) THEN
    GIVEHINT;
END;  {BIRDHINT}
PROCEDURE SNAKEHINT;
BEGIN {SNAKEHINT}
  IF HERE(SNAKE) AND NOT HERE(BIRD) THEN
    GIVEHINT
  ELSE
    VARY^.HINTLC[HINT]:=0;
END;  {SNAKEHINT}
PROCEDURE MAZEHINT;
BEGIN {MAZEHINT}
  IF (VARY^.ATLOC[VBL^.LOC]=0) AND (VARY^.ATLOC[VBL^.OLDLOC]=0) AND
     (VARY^.ATLOC[VBL^.OLDLC2]=0) AND (VBL^.HLDING>1) THEN
    GIVEHINT
  ELSE
    VARY^.HINTLC[HINT]:=0;
END;  {MAZEHINT}
PROCEDURE DARKHINT;
BEGIN {DARKHINT}
  IF (VARY^.PROP[EMERALD]<>-1) AND (VARY^.PROP[PYRAMID]=-1) THEN
    GIVEHINT
  ELSE
    VARY^.HINTLC[HINT]:=0;
END;  {DARKHINT}
PROCEDURE WITTHINT;
BEGIN {WITTHINT}
  GIVEHINT;
END;  {WITTHINT}
BEGIN { CHECKHINTS}
  FOR HINT:=4 TO HNTSIZ DO
  BEGIN
    IF NOT VARY^.HINTED[HINT] THEN
    BEGIN
      IF BITSET(VBL^.LOC,HINT) THEN
        VARY^.HINTLC[HINT]:=VARY^.HINTLC[HINT]+1
      ELSE
        VARY^.HINTLC[HINT]:=0;
      IF VARY^.HINTLC[HINT]>= ARY^.HINTS[HINT,1] THEN
        CASE HINT OF
          4 : CAVEHINT;
          5 : BIRDHINT;
          6 : SNAKEHINT;
          7 : MAZEHINT;
          8 : DARKHINT;
          9 : WITTHINT;
        END; {CASE OF HINT}
    END;
  END;
END;  { CHECKHINTS}
PROCEDURE SET_NEW_LOC;
VAR
  T1,T2,T3 : BOOLEAN;
PROCEDURE PLOVERALCOVE;
BEGIN { PLOVERALCOVE }
  NEWLOC:=199 - VBL^.LOC;
  IF (VBL^.HLDING=0) OR ((VBL^.HLDING=1) AND TOTING(EMERALD)) THEN
  ELSE
  BEGIN
    NEWLOC:=VBL^.LOC;
    SPEAK(ARY^.RTEXT[117]);
  END;
  EXIT(SET_NEW_LOC);
END;  { PLOVERALCOVE }
PROCEDURE TROLLBRIDGE;
BEGIN { TROLLBRIDGE }
  IF VARY^.PROP[TROLL]=1 THEN
  BEGIN
    PSPEAK(TROLL,1);
    VARY^.PROP[TROLL]:=0;
    MOVE(TROLL2,0);
    MOVE(TROLL2+100,0);
    MOVE(TROLL,ARY^.PLAC[TROLL]);
    MOVE(TROLL+100,ARY^.FIXD[TROLL]);
    JUGGLE(CHASM);
    NEWLOC:=VBL^.LOC;
  END
  ELSE
  BEGIN
    NEWLOC:=ARY^.PLAC[TROLL]+ARY^.FIXD[TROLL]-VBL^.LOC;
    IF VARY^.PROP[TROLL]=0 THEN
      VARY^.PROP[TROLL]:=1;
    IF TOTING(BEAR) THEN
    BEGIN
      SPEAK(ARY^.RTEXT[162]);
      VARY^.PROP[CHASM]:=1;
      VARY^.PROP[TROLL]:=2;
      DROP(BEAR,NEWLOC);
      VARY^.FIXED[BEAR]:=-1;
      VARY^.PROP[BEAR]:=3;
      IF VARY^.PROP[SPICES]<0 THEN
        VBL^.TALLY2:=VBL^.TALLY2+1;
      VBL^.OLDLC2:=NEWLOC;
      HE_DIED:=TRUE;
    END;
  END;
  EXIT(SET_NEW_LOC);
END;  { TROLLBRIDGE }
BEGIN { SET_NEW_LOC }
  KK:=ARY^.KEY[VBL^.LOC];
  IF KK=0 THEN
    ERRORHALT(26);
  NEWLOC:=VBL^.LOC;
  IF K=NULL THEN
    EXIT(SET_NEW_LOC);
  SKIPIT:=FALSE;
  IF K=BACK THEN
  BEGIN {BACK}
    SKIPIT:=TRUE;
    IF FORCED(K) THEN
      K:=VBL^.OLDLC2
    ELSE
      K:=VBL^.OLDLOC;
    VBL^.OLDLC2:=VBL^.OLDLOC;
    VBL^.OLDLOC:=VBL^.LOC;
    K2:=0;
    IF K=VBL^.LOC THEN
    BEGIN
      SPEAK(ARY^.RTEXT[91]);
      EXIT(SET_NEW_LOC);
    END;
    OK:=FALSE;
    KK:=KK-1;
    REPEAT
      KK:=KK+1;
      IF K=ARY^.TRAVEL2[KK] THEN
      BEGIN
        K:=ABS(ARY^.TRAVEL[KK]);
        KK:=ARY^.KEY[VBL^.LOC];
        OK:=TRUE;
      END
      ELSE
      BEGIN
        IF ARY^.TRAVEL2[KK]<=300 THEN
        BEGIN
          J:=ARY^.KEY[ARY^.TRAVEL2[KK]];
          IF FORCED(ARY^.TRAVEL2[KK]) AND (ARY^.TRAVEL2[J]=K) THEN
            K2:=KK;
        END;
        IF ARY^.TRAVEL[KK]<0 THEN
        BEGIN
          KK:=K2;
          IF KK=0 THEN
          BEGIN
            SPEAK(ARY^.RTEXT[140]);
            EXIT(SET_NEW_LOC);
          END;
          K:=ABS(ARY^.TRAVEL[KK]);
          KK:=ARY^.KEY[VBL^.LOC];
          OK:=TRUE;
        END;
      END;
    UNTIL OK OR (ARY^.TRAVEL2[KK]=K);
  END;   {BACK}
  IF K=LOOK THEN
  BEGIN {LOOK}
    IF VBL^.DETAIL<3 THEN
      SPEAK(ARY^.RTEXT[15]);
    VBL^.DETAIL:=VBL^.DETAIL+1;
    VBL^.WZDARK:=FALSE;
    VARY^.ABB[VBL^.LOC]:=0;
  END   {LOOK}
  ELSE  {LOOK}
    IF K=CAVE THEN
    BEGIN {CAVE}
      IF VBL^.LOC<8 THEN
        SPEAK(ARY^.RTEXT[57])
      ELSE
        SPEAK(ARY^.RTEXT[58]);
    END   {CAVE}
    ELSE  {CAVE}
    BEGIN {NOT SPECIAL}
      IF NOT SKIPIT THEN
      BEGIN
        VBL^.OLDLC2:=VBL^.OLDLOC;
        VBL^.OLDLOC:=VBL^.LOC;
      END;
      { TRAVEL  = VERB               }
      { TRAVEL2 = WHERE TO GO        }
      { TRAVEL3 = CONDITION (IF ANY) }
      KK:=KK-1;
      REPEAT
        KK:=KK+1;
        OK:=(ABS(ARY^.TRAVEL[KK])=1) OR (ABS(ARY^.TRAVEL[KK])=K);
      UNTIL OK OR (ARY^.TRAVEL[KK]<0);
      IF NOT OK THEN
      BEGIN
        SPK:=12;
        CASE K OF
          43,44,45,46,47,48,49,50,29,30 : SPK:=9;
          7,36,37 : SPK:=10;
          11,19 : SPK:=11;
          62,65 : SPK:=42;
          17 : SPK:=80;
        END;
        IF (VBL^.VERB=FIND) OR (VBL^.VERB=INVENTORY) THEN
          SPK:=59;
        SPEAK(ARY^.RTEXT[SPK]);
        EXIT(SET_NEW_LOC);
      END;
      REPEAT
        NEWLOC:=ARY^.TRAVEL2[KK];
        TVCOND:=ARY^.TRAVEL3[KK];
        K:=TVCOND MOD 100;
        IF K=0 THEN
        BEGIN
          T1:=FALSE;
          T2:=FALSE;
          T3:=FALSE;
        END
        ELSE
        BEGIN
          T1:=TOTING(K);
          T2:=AT(K);
          T3:=VARY^.PROP[K]<>(TVCOND DIV 100 -3)
        END;
        IF ((TVCOND<=100) AND 
            ((TVCOND=0) OR PERCENT(TVCOND))) OR
           ((TVCOND>100) AND (TVCOND<=300) AND 
            (T1 OR ((TVCOND>200) AND T2))) OR
           ((TVCOND>300) AND T3) THEN
        BEGIN
          IF NEWLOC<=300 THEN
            EXIT(SET_NEW_LOC);
          IF NEWLOC<=500 THEN
          BEGIN
             NEWLOC:=NEWLOC-300;
             IF NEWLOC=1 THEN
               PLOVERALCOVE
             ELSE
               IF NEWLOC=2 THEN
                 DROP(EMERALD,VBL^.LOC)
               ELSE
                 IF NEWLOC=3 THEN
                   TROLLBRIDGE
                 ELSE
                   ERRORHALT(20);
          END
          ELSE
          BEGIN
            SPEAK(ARY^.RTEXT[NEWLOC-500]);
            NEWLOC:=VBL^.LOC;
            EXIT(SET_NEW_LOC);
          END;
        END;
        REPEAT
          IF ARY^.TRAVEL[KK]<0 THEN
            ERRORHALT(25);
          KK:=KK+1;
        UNTIL (TVCOND<>ARY^.TRAVEL3[KK]) AND
              (NEWLOC<>ARY^.TRAVEL2[KK]);
      UNTIL FALSE; { EXIT IS BY EXIT PROC}
    END; {NOT SPECIAL}
END;  { SET_NEW_LOC }

